// ---------------------------------------------------------------------------
//  File:geo_spatial.h
//
//  Description: Contains the data types, constants, and forward declarations
//               used for geodesy related functions
//
//  Author: golden.colorado.5280@gmail.com
//
//  Adapted from:
//      This application uses geodesy algorithms from the open source library
//      geostarslib-0.9.3. This software is available at the following URL.
//      http://sourceforge.net/projects/geostarslib/files/geoStarLib-0.9.3/
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
//  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//  DEALINGS IN THE SOFTWARE.
// ---------------------------------------------------------------------------


#ifndef GEO_SPATIAL_H_INCLUDED
#define GEO_SPATIAL_H_INCLUDED

#include <math.h>

//----WGS84 Model Ellipsoid Parameters
#define WGS84_a                 6378137.0           //Semi-major Axis (meters)
#define WGS84_fl                298.257223563       //Flattening Factor of the Earth  (no units)
#define GEO_B(a,f)              (a*(1.0-(1.0/f)))
#define GEO_FL(f)               (1.0/f)
#define GEO_E2(a,f)             (((a*a) - ((GEO_B(a,f))*(GEO_B(a,f))))/(a*a))
#define GEO_E2P(a,f)            (((a*a) - ((GEO_B(a,f))*(GEO_B(a,f))))/((GEO_B(a,f))*(GEO_B(a,f))))
#define PI                      3.14159265358979323846
#define DEG_TO_RAD              (M_PI/180.0)    //Degrees to Radians conversion factor
#define RAD_TO_DEG              (180.0/M_PI)    //Radians to Degrees conversion factor
#define KM_TO_M                 1000.0

//---Define indices for 3-element coordinate set arrays
#define   GEO_E       0         //E coordinate of Earth Fixed Geocentric coordinate ( METERS )
#define   GEO_F       1         //F coordinate of Earth Fixed Geocentric coordinate ( METERS )
#define   GEO_G       2         //G coordinate of Earth Fixed Geocentric coordinate ( METERS )
#define   GEO_X       0         //X or East coordinate of the local tangential plane ( METERS )
#define   GEO_Y       1         //Y or North coordinate of the local tangential plane ( METERS )
#define   GEO_Z       2         //Z or Up coordinate of the local tangential plane ( METERS )
#define   GEO_RNG     0         //Slant range ( METERS )
#define   GEO_AZ      1         //Azimuth, clockwise from north
#define   GEO_EL      2         //Elevation, from horizon (0) up

typedef struct {
   double a;      // Major Earth axis in meters */
   double b;      // Minor Earth axis in meters */
   double flat;   // Earth flattening value */
   double e2;     // Eccentricity squared */
   double ee2;    // Eccentricity squared prime */
   double m1e2;   // 1 - eccentricity squared */
   double bee2;   // b * ee2 */
   double ae2;    // a * e2 */
   double aob;    // a / b */
} GEO_DATUM;

//---Structure holds all of the pertinent location, ellipsoid, and datum data associated with a location
typedef struct{
    /* Ellipsoid values - this data is now stored in the datum structure */
   GEO_DATUM datum; // Datum that this location is in. */

   /* Geodetic coordinates */
   double lat;     // Site Latitude in decimal degrees */
   double lon;     // Site Longitude in decimal degrees */
   double hgt;     // Site Height above the ellipsoid in meters */

   double rlat;    // Radian value of latitude */
   double rlon;    // Radian value of longitude */

   /* Sine and Cosine values */
   double slat;    // Sine of latitude */
   double clat;    // Cosine of latitude */
   double slon;    // Sine of longitude */
   double clon;    // Cosine of longitude */
   double tlat;    // Tangent of latitude */

   /* Precomputed values (for speed) */
   double clonclat; // Cos(lon) * Cos(lat) */
   double slonslat; // Sin(lon) * Sin(lat) */
   double clonslat; // Cos(lon) * Sin(lat) */
   double slonclat; // Sin(lon) * Cos(lat) */

   double n;        // Radius of curvature */
   double m;        // Meridional radius of curvature */

   /* Geocentric coordinates */
   double e;       // X : Earth Fixed Geocentric (XYZ) Coordinates */
   double f;       // Y : Earth Fixed Geocentric (XYZ) Coordinates */
   double g;       // Z : Earth Fixed Geocentric (XYZ) Coordinates */
   double efg[3];  // EFG: array of XYZ */

} GEO_LOCATION;

//Forward Declarations
void define_observer(GEO_LOCATION*, double, double, double);
void geoRae2Efg (GEO_LOCATION*,double [], double []);
void geoEfg2Llh (GEO_LOCATION*, double [], double*, double*, double*);

#endif // GEO_SPATIAL_H_INCLUDED
